/**
  ******************************************************************************
  * @file    ACAD_DRIVER.c
  * @author  Feirui_Joe
  * @version V0.1
  * @date    07/26/2010
  * @brief   ACAD Handling
  ******************************************************************************
  * @copy
  *
  * <h2><center>&copy; COPYRIGHT 2010 Feirui</center></h2>
  */ 



/**
  * @brief  INCLUDE FILES.
  */
#ifndef	ACAD_DRIVER_GLOBALS
#define	ACAD_DRIVER_GLOBALS
#include <includes.h>


                                      /***************************************/
                                      /*             ADC handling            */
                                      /***************************************/


/************************************/
/*    Start AC ADC Measurement      */
/************************************/

void Enable_ADCTimerMeasure(void)
{
  /* ENABLE ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  /* ENABLE ADC2 */
  ADC_Cmd(ADC2, ENABLE);
  /* Enable ADC1 external trigger */ 
  ADC_ExternalTrigConvCmd(ADC1, ENABLE);
	
	/* Disable the CCx Interrupt Request */
  DMA_ITConfig(Cfg3ADCDMA_Channel,Cfg3ADCDMA_Channel_IT, ENABLE);
	
	/* Timer Start */
	TIM_Cmd(ADCSampleTIMx, ENABLE);
}



/************************************/
/*    Initial ADC Sample Freq       */
/************************************/

static void RCC_ADCSampleFreqCfg(void);
static void GPIO_ADCSampleFreqCfg(void); 
static void TIM_ADCSampleFreqCfg(void);

/* Initial ADC sample Freq Config */
void ADCSampleFreqCfg_Init  (void)
{
  /* System Clocks Configuration */
  RCC_ADCSampleFreqCfg();
  
  /* Re-map TIM1 OC1 output pin */
  GPIO_ADCSampleFreqCfg(); 
  
  /* Configure the Timer */
  TIM_ADCSampleFreqCfg();
}


/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval None
  */
static void RCC_ADCSampleFreqCfg(void)
{
  /* TIM clock enable */
  RCC_APB1PeriphClockCmd(ADCSampleTIMx_RCCPeriph, ENABLE);
}

/**
  * @brief  Configures the different GPIO ports.
  * @param  None
  * @retval None
  */
static void GPIO_ADCSampleFreqCfg(void)
{
  /* TIM Channel remapping pins */
//  GPIO_PinRemapConfig(GPIO_PinRemap_TIM2OC2, ENABLE);
}


/**
  * @brief  Configure TIM.
  * @param  None
  * @retval None
  */
static void TIM_ADCSampleFreqCfg(void)
{
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  
  /* Disable TIM counter */
  TIM_Cmd(ADCSampleTIMx, DISABLE);
  /* Clear TIM Flag */
  TIM_ClearFlag(ADCSampleTIMx,ADCSampleTIMx_FLAGx);
  /* Clear TIM Pending Bit */
  TIM_ClearITPendingBit(ADCSampleTIMx,ADCSampleTIMx_ITx);
  
  /* Choose Internal Clock */
  TIM_InternalClockConfig(ADCSampleTIMx);
  
  /* Time Base configuration */
  TIM_TimeBaseStructure.TIM_Prescaler         = ADCSampleTIMx_Prescaler        ;
  TIM_TimeBaseStructure.TIM_CounterMode       = ADCSampleTIMx_CounterMode      ;
  TIM_TimeBaseStructure.TIM_Period            = ADCSampleTIMx_Period           ;
  TIM_TimeBaseStructure.TIM_ClockDivision     = ADCSampleTIMx_ClockDivision    ;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = ADCSampleTIMx_RepetitionCounter;
  TIM_TimeBaseInit(ADCSampleTIMx, &TIM_TimeBaseStructure);
  /* Disable reload ARR after EVENT */
  TIM_ARRPreloadConfig(ADCSampleTIMx,DISABLE);
  
  /* Output Compare Active Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OCMode       = ADCSampleTIMx_OCMode      ;
  TIM_OCInitStructure.TIM_OutputState  = ADCSampleTIMx_OutputState ;
  TIM_OCInitStructure.TIM_OutputNState = ADCSampleTIMx_OutputNState;
  TIM_OCInitStructure.TIM_Pulse        = ADCSampleTIMx_Pulse       ;
  TIM_OCInitStructure.TIM_OCPolarity   = ADCSampleTIMx_OCPolarity  ;
  TIM_OCInitStructure.TIM_OCNPolarity  = ADCSampleTIMx_OCNPolarity ;
  TIM_OCInitStructure.TIM_OCIdleState  = ADCSampleTIMx_OCIdleState ;
  TIM_OCInitStructure.TIM_OCNIdleState = ADCSampleTIMx_OCNIdleState;
  TIM_OC2Init(ADCSampleTIMx, &TIM_OCInitStructure);
  /* Disable reload CR2 after EVENT */
  TIM_OC2PreloadConfig(ADCSampleTIMx, TIM_OCPreload_Disable);
  
  /* TIM2 main Output Enable */
  TIM_CtrlPWMOutputs(ADCSampleTIMx, ENABLE);
}




/************************************/
/*    Initial ADC Measure */
/************************************/
static void RCC_ADCMeasureCfg  (void);
static void GPIO_ADCMeasureCfg (void);
static void Caliba_ADC12hardware (void);
static void NVIC_ADCDMAConfig(FunctionalState TIMCtrSta);
static void Reset_Cfg3DMA_ADC(void);
static void Init_DMA_ADCConfig3(void);

/* Initial ADC Measure Config */
void ADCMeasureCfg3_Init  (void)
{
  /* System Clocks Configuration */
  RCC_ADCMeasureCfg();
  
  /* Configure the GPIO ports */
  GPIO_ADCMeasureCfg();
  /* Disable INT */
  NVIC_ADCDMAConfig(DISABLE);
  
  /* Initial ADC&&DMA config */
  Init_DMA_ADCConfig3();
  
  /* ADC calibaration */
  Caliba_ADC12hardware();
  
  /* Enable INT */
  NVIC_ADCDMAConfig(ENABLE);
}

/**
  * @brief  Configures RCC clock for ADC
  * @param  None
  * @retval None
  */
static void RCC_ADCMeasureCfg(void)
{
	uint32_t RCC_APBxPeriph_GPIOx;
	uint8_t  i;
  
  /* Set ADCCLK */
  RCC_ADCCLKConfig(SYSADCCLK_FREQ);
  
  /* Enable DMA clock */
  RCC_AHBPeriphClockCmd(Cfg3ADCDMA_RCCPeriph, ENABLE);
  
  /* Enable ADC1, ADC2 and GPIOx clock */
  for(i=0,RCC_APBxPeriph_GPIOx=0;i<ACADCPortCfgNumber;i++)
    RCC_APBxPeriph_GPIOx|=ACADCPortCfgTbl[i].RCC_APB2Periph;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 |
                         RCC_APBxPeriph_GPIOx, ENABLE);
}

/**
  * @brief  Configures GPIO
  * @param  None
  * @retval None
  */
static void GPIO_ADCMeasureCfg(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  uint8_t i;
  
  /* Configuration Port for ADC pin */
  for(i=0;i<ACADCPortCfgNumber;i++)
  {
    GPIO_InitStructure.GPIO_Pin   = ACADCPortCfgTbl[i].GPIO_Pin;
    GPIO_InitStructure.GPIO_Speed = ACADCPortCfgTbl[i].GPIO_Speed;
    GPIO_InitStructure.GPIO_Mode  = ACADCPortCfgTbl[i].GPIO_Mode;
    GPIO_Init(ACADCPortCfgTbl[i].GPIOx, &GPIO_InitStructure);
  }
}



/**
  * @brief  Reset ADC && DMA
  * @param  None
  * @retval None
  */
static void Reset_Cfg3DMA_ADC(void)
{
	/* Disable ADC1 */
  ADC_Cmd(ADC1, DISABLE);
  /* Disable ADC2 */
  ADC_Cmd(ADC2, DISABLE);
	
  /* Disable ADC1 external trigger conversion */
  ADC_ExternalTrigConvCmd(ADC1, DISABLE);
  /* Disable ADC2 external trigger conversion */
  ADC_ExternalTrigConvCmd(ADC2, DISABLE);
  /* Disable ADC1 DMA */
  ADC_DMACmd(ADC1, DISABLE);
  /* Disable DMAx Channelx */
  DMA_Cmd(Cfg3ADCDMA_Channel, DISABLE);
  
	/* Disable the CCx Interrupt Request */
  DMA_ITConfig(Cfg3ADCDMA_Channel,Cfg3ADCDMA_Channel_IT, DISABLE);
	/* Clear DMA interrupt pending bit */
	DMA_ClearITPendingBit(Cfg3ADCDMA_IT_Mode);
	/* Clear DMA Event Flag */
	DMA_ClearFlag(Cfg3ADCDMA_FLAG_Mode);
}


/* NVIC configuration */
static void NVIC_ADCDMAConfig(FunctionalState TIMCtrSta)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Enable the DMA1 TX Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel                   = Cfg3ADCDMA_IRQChannel;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = Cfg3ADCDMA_IRQPrePrio;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority        = Cfg3ADCDMA_IRQSubPrio;
  NVIC_InitStructure.NVIC_IRQChannelCmd                = TIMCtrSta;
  NVIC_Init(&NVIC_InitStructure);  
}


static void Init_DMA_ADCConfig3(void)
{
  ADC_InitTypeDef ADC_InitStructure;
  uint8_t i;
  
  /*Reset ADC && DMA*/
  Reset_Cfg3DMA_ADC();   

  /* DMAx channelx configuration ----------------------------------------------*/
  ACADCDMAInitStructure.DMA_PeripheralBaseAddr = Cfg3ADCDMA_PeripheralBaseAddr;
  ACADCDMAInitStructure.DMA_MemoryBaseAddr     = ADCACBufferAreaAddress[ACMeasureBufferAreaNum%ADCBufferAreaNumb];
  ACADCDMAInitStructure.DMA_DIR                = Cfg3ADCDMA_DIR               ;
  ACADCDMAInitStructure.DMA_BufferSize         = Cfg3ADCDMA_BufferSize        ;
  ACADCDMAInitStructure.DMA_PeripheralInc      = Cfg3ADCDMA_PeripheralInc     ;
  ACADCDMAInitStructure.DMA_MemoryInc          = Cfg3ADCDMA_MemoryInc         ;
  ACADCDMAInitStructure.DMA_PeripheralDataSize = Cfg3ADCDMA_PeripheralDataSize;
  ACADCDMAInitStructure.DMA_MemoryDataSize     = Cfg3ADCDMA_MemoryDataSize    ;
  ACADCDMAInitStructure.DMA_Mode               = Cfg3ADCDMA_Mode              ;
  ACADCDMAInitStructure.DMA_Priority           = Cfg3ADCDMA_Priority          ;
  ACADCDMAInitStructure.DMA_M2M                = Cfg3ADCDMA_M2M               ;
  DMA_Init(Cfg3ADCDMA_Channel, &ACADCDMAInitStructure);
  /* Enable DMAx Channelx */
  DMA_Cmd(Cfg3ADCDMA_Channel, ENABLE);
  
  
  /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode               = Cfg3ADC1_Mode              ;
  ADC_InitStructure.ADC_ScanConvMode       = Cfg3ADC1_ScanConvMode      ;
  ADC_InitStructure.ADC_ContinuousConvMode = Cfg3ADC1_ContinuousConvMode;
  ADC_InitStructure.ADC_ExternalTrigConv   = Cfg3ADC1_ExternalTrigConv  ;
  ADC_InitStructure.ADC_DataAlign          = Cfg3ADC1_DataAlign         ;
  ADC_InitStructure.ADC_NbrOfChannel       = Cfg3ADC1_NbrOfChannel      ;
  ADC_Init(ADC1, &ADC_InitStructure);
  /* ADC1 regular channels configuration */
  for(i=0;i<Cfg3ADC_RegularNumber;i++)
    ADC_RegularChannelConfig(ADC1,ACADCRegularCfg3Tbl[0][i].ADC_Channel,ACADCRegularCfg3Tbl[0][i].Rank,ACADCRegularCfg3Tbl[0][i].ADC_SampleTime);
  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);
  
  
  /* ADC2 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode               = Cfg3ADC2_Mode              ;
  ADC_InitStructure.ADC_ScanConvMode       = Cfg3ADC2_ScanConvMode      ;
  ADC_InitStructure.ADC_ContinuousConvMode = Cfg3ADC2_ContinuousConvMode;
  ADC_InitStructure.ADC_ExternalTrigConv   = Cfg3ADC2_ExternalTrigConv  ;
  ADC_InitStructure.ADC_DataAlign          = Cfg3ADC2_DataAlign         ;
  ADC_InitStructure.ADC_NbrOfChannel       = Cfg3ADC2_NbrOfChannel      ;
  ADC_Init(ADC2, &ADC_InitStructure);
  /* ADC2 regular channels configuration */ 
  for(i=0;i<Cfg3ADC_RegularNumber;i++)
    ADC_RegularChannelConfig(ADC2,ACADCRegularCfg3Tbl[1][i].ADC_Channel,ACADCRegularCfg3Tbl[1][i].Rank,ACADCRegularCfg3Tbl[1][i].ADC_SampleTime);
  /* Enable ADC2 external trigger conversion */
  ADC_ExternalTrigConvCmd(ADC2, ENABLE);

  // Enable the temperature sensor and vref internal channel 
  ADC_TempSensorVrefintCmd(ENABLE);
}

/**
  * @brief  ADC calibaration
  * @param  None
  * @retval None
  */
static void Caliba_ADC12hardware(void)
{
  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  
  /* Enable ADC1 reset calibaration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));
  
  /* Start ADC1 calibaration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));
  
  /* Disable ADC1 */
  ADC_Cmd(ADC1, DISABLE);
  
  /************************************/
  
  /* Enable ADC2 */
  ADC_Cmd(ADC2, ENABLE);
  
  /* Enable ADC2 reset calibaration register */   
  ADC_ResetCalibration(ADC2);
  /* Check the end of ADC2 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC2));
  
  /* Start ADC2 calibaration */
  ADC_StartCalibration(ADC2);
  /* Check the end of ADC2 calibration */
  while(ADC_GetCalibrationStatus(ADC2));
  
  /* Disable ADC2 */
  ADC_Cmd(ADC2, DISABLE);
  
}




/*$PAGE*/#endif	/*	ACAD_DRIVER_GLOBALS	*/
